/**
 * @author Administrador
 * Created on 17/11/2005
 * Updated on 02/04/2010
 */
package br.unb.graphics.qos.charts;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

import br.unb.core.traffic.Traffic;

public class LossChart extends GenericQosChart {

    long windowSize = 2000;
    private static final String LOSS = "loss";//will look in on QosChart.properties

    public LossChart(long window) {
        super(LOSS);
        windowSize = window;
    }

    public void setWindowSize(long windowSize) {
        this.windowSize = windowSize;
        super.setWindowLabel(windowSize);
    }

    public void addQosToTraffic(
            int nrPacket,
            int lenPacket,
            long sendTime,
            long receiveTime,
            String trafficName) {
        Vector values = (Vector) super.vectorsMap.get(trafficName);
        if (values != null) {
            values.add(new Value(receiveTime, nrPacket));
        }

    }

    /**
     * Adds a traffic to the graffic
     * @param trafficName Name of the traffic to be added must be unique
     */
    public synchronized void addTrafficToQos(String trafficName) {
        if (this.vectorsMap.get(trafficName) == null) {
            Vector values = new Vector();
            values.add(new Value(0, 0));
            this.vectorsMap.put(trafficName, values);
            this.addTraffic(trafficName);
        }
    }

    /**
     * Adds the vector values to the graffics
     *           ----countValues---
     * ---------+------------------+-------------
     *       lowerValue            upperValue
     *The packetLoss is stored in the first memory position
     */
    public void addValuesToCharts() {


        String name = "";
        Vector values;
        Value value = null;
        double countPacketLoss = 0;
        int nr = 0, lowerNr = 0, upperNr = 0;
        Iterator iterator = vectorsMap.keySet().iterator();

        while (iterator.hasNext()) {
            name = (String) iterator.next();
            values = (Vector) vectorsMap.get(name);

            countPacketLoss = (int) ((Value) values.get(0)).getValue();
            if (values.size() > 2) {

                value = (Value) values.get(1);
                nr = (int) value.getValue();
                lowerNr = nr;
                upperNr = nr;
                for (int i = 2; i < values.size(); i++) {
                    value = (Value) values.get(i);
                    nr = (int) value.getValue();
                    if (nr < lowerNr) {
                        lowerNr = nr;
                    } else if (nr > upperNr) {
                        upperNr = nr;
                    }

                }

                countPacketLoss = 100.0d * ((upperNr - lowerNr) - (values.size() - 2)) / (upperNr - lowerNr);
                super.addValueToTraffic(countPacketLoss, ((Value) values.get(values.size() - 1)).getTimestamp(), name);

                values = new Vector();
                values.add(new Value(0, countPacketLoss));
                values.add(new Value(value.getTimestamp(), upperNr));
                vectorsMap.put(name, values);
                lowerNr = 0;
                upperNr = 0;
            }

        }

    }

    @Override
    public void loadValuesFromFile(File file) {
        //This method only works suposing the graffics where added on this order:
        //delay, jitter, loss, bandwidth

        try {
            FileInputStream fis = new FileInputStream(file);
            LineNumberReader lnr = new LineNumberReader(new InputStreamReader(fis));
            String nextStringTraffic = "";
            StringTokenizer st;
            int start = 0;
            String trafficName;
            while (!nextStringTraffic.startsWith("#Traffic:") && ((nextStringTraffic = lnr.readLine()) != null));
//			for(int i = 0; i<4 && ((nextStringTraffic = lnr.readLine())!=null );i++);
            if (nextStringTraffic.startsWith("#Traffic:")) {

                Traffic traffic = Traffic.fromString(nextStringTraffic.substring(nextStringTraffic.indexOf(":") + 1));
                trafficName = traffic.getName();
                start = traffic.getStart();
            } else {
                trafficName = file.getName();
            }

            super.addTraffic(trafficName);

            double lossAmout = 0;
            int nrPacket, minNrPack = 0, maxNrPack = 0, countPack = 0;
            long receiveTime = 0, firstReceivedTime = 0, refReceiveTime = 0, n = 1;
            while ((nextStringTraffic = lnr.readLine()) != null && !nextStringTraffic.startsWith("#NrPacket"));
            //The first value is different : does not have jitter
            if ((nextStringTraffic = lnr.readLine()) != null) {
                st = new StringTokenizer(nextStringTraffic, "\t");
                try {
                    nrPacket = Integer.parseInt(st.nextToken());
                    minNrPack = nrPacket;
                    maxNrPack = nrPacket;
                    countPack = 0;
                    st.nextToken();
                    st.nextToken();
                    receiveTime = Long.parseLong(st.nextToken());
                    firstReceivedTime = receiveTime;
                    refReceiveTime = receiveTime - 3 * 60 * 60 * 1000000L - 1000000L * start; //Adjusts to go to 0hs
                } catch (NumberFormatException nfe) {
                }
            }
            while ((nextStringTraffic = lnr.readLine()) != null) {
                st = new StringTokenizer(nextStringTraffic, "\t");
                try {

                    nrPacket = Integer.parseInt(st.nextToken());
                    st.nextToken();
                    st.nextToken();
                    receiveTime = Long.parseLong(st.nextToken());

                    if (nrPacket > maxNrPack) {
                        maxNrPack = nrPacket;
                    } else if (nrPacket < minNrPack) {
                        minNrPack = nrPacket;
                    }
                    countPack++;

                    if (receiveTime - firstReceivedTime < n * (windowSize) * 1000) {
                    } else {//Fim da janela
                        lossAmout = ((maxNrPack - minNrPack) - countPack) * 100.0d / (maxNrPack - minNrPack);
                        super.addValueToTraffic((double) lossAmout, (receiveTime - refReceiveTime), trafficName);
                        minNrPack = maxNrPack;
                        countPack = 0;
                        n++;
                    }
                } catch (NumberFormatException nfe) {
                }
            }
            lnr.close();
            fis.close();
        } catch (IOException ioe) {
        }
        Runtime.getRuntime().gc();
    }
}
